package org.jinghouyu.http.proxy.server;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.jinghouyu.http.proxy.server.callback.RequestHandler;
import org.jinghouyu.http.proxy.server.callback.ResponseHandler;

/**
 * Proxy Server. 
 * @author liujingyu
 *
 */
public class ProxyServer {
	
	private static final Logger logger = Logger.getLogger(ProxyServer.class);
	
	private int port = 0;
	private ServerSocket listener = null;
	private boolean hasStart = false;
	
	private List<RequestHandler> requestHandlers = null;
	private List<ResponseHandler> responseHandlers = null;
	
	public ProxyServer(int port) {
		this.port = port;
	}
	
	public ProxyServer() {
		this(8088);
	}
	
	public synchronized void start() {
		if(!hasStart) {
			try {
				listener = new ServerSocket(port);
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
			new Thread(){
				public void run() {
					_run();
				}
			}.start();
			hasStart = true;
		} else {
			if(logger.isDebugEnabled()) {
				logger.debug("server has been already started");
			}
		}
	}
	
	private void _run() {
		while(true) {
			try {
				Socket socket = listener.accept();
				processSocket(socket);
			} catch (IOException e) {
				if(logger.isDebugEnabled()) {
					logger.debug("connection errors", e);
				}
			}
		}
	}
	
	private void processSocket(Socket socket) {
		new ClientProxier(this, socket).start();
	}
	
	public void addRequestHandler(RequestHandler requestHandler) {
		if(requestHandlers == null) {
			requestHandlers = new ArrayList<>();
		}
		requestHandlers.add(requestHandler);
	}
	
	public void removeRequestHandler(RequestHandler requestHandler) {
		if(requestHandlers == null) return;
		requestHandlers.remove(requestHandler);
	}
	
	public void addResponseHandler(ResponseHandler responseHandler) {
		if(responseHandlers == null) {
			responseHandlers = new ArrayList<>();
		}
		responseHandlers.add(responseHandler);
	}
	
	public void removeResponseHandler(ResponseHandler responseHandler) {
		if(responseHandler == null) return;
		responseHandlers.remove(responseHandler);
	}

	public List<RequestHandler> getRequestHandlers() {
		return requestHandlers;
	}

	public List<ResponseHandler> getResponseHandlers() {
		return responseHandlers;
	}
}
